﻿namespace Hopfield.Simulator
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Globalization;
    using System.IO;
    using System.Reflection;
    using System.Threading;
    using System.Windows.Forms;    

    public static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        public static void Main()
        {
            ApplicationInit();
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }

        private static void HandleException(Exception ex)
        {
            string message = string.Empty;
            Exception iex = ex;
            while (iex != null)
            {
                message += string.Format(CultureInfo.InvariantCulture, "{0}{1}{2}{3}{4}{5}{6}{7}",
                    DateTime.Now,
                    Environment.NewLine,
                    iex.GetType().ToString(),
                    Environment.NewLine,
                    iex.Message,
                    Environment.NewLine,
                    iex.StackTrace,
                    Environment.NewLine);
                iex = iex.InnerException;
            }

            Trace.Write(message);
            Trace.Flush();
            try
            {
                using (ExceptionForm exf = new ExceptionForm(ex))
                {
                    exf.ShowDialog();
                }
            }
            catch
            {
                Application.Exit();
            }
        }

        private static void ApplicationInit()
        {
            // Language
            Application.CurrentCulture = new CultureInfo("en-US");
            Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");

            // Trace
            TextWriterTraceListener listener = new TextWriterTraceListener(AppDomain.CurrentDomain.BaseDirectory + "\\TraceLog.txt");
            Trace.Listeners.Add(listener);            

            // Unhandled exceptions
            Application.ThreadException += (sender, e) =>
            {
                Exception ex = e.Exception as Exception;
                if (ex == null)
                {
                    return;
                }

                HandleException(ex);
            };

            Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

            AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
            {
                Exception ex = e.ExceptionObject as Exception;
                if (ex == null)
                {
                    return;
                }

                HandleException(ex);
            };

            if (false == Directory.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\Plugins")) return;

            foreach (string fileName in Directory.GetFiles(
                AppDomain.CurrentDomain.BaseDirectory + "\\Plugins",
                "*.dll",
                SearchOption.TopDirectoryOnly))
            {
                Assembly addonAssembly = null;
                byte[] rawAssembly = File.ReadAllBytes(fileName);
                string pdbFileName = fileName.Substring(0, fileName.Length - 3) + "pdb";
                if (true == Directory.Exists(pdbFileName))
                {                    
                    byte[] rawSymbolStore = File.ReadAllBytes(pdbFileName);
                    addonAssembly = AppDomain.CurrentDomain.Load(rawAssembly, rawSymbolStore);
                }
                else
                {
                    addonAssembly = AppDomain.CurrentDomain.Load(rawAssembly);
                }
            }
        }
    }
}
